package main

import (
	"context"
	"fmt"
	"os"
	"time"
	"wanfang-translation/internal/service"
	"wanfang-translation/internal/service/check"
	"wanfang-translation/internal/service/exception"

	"github.com/spf13/viper"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

// Config 配置结构体
type Config struct {
	RabbitMQ struct {
		Host     string `mapstructure:"host"`
		Port     int    `mapstructure:"port"`
		User     string `mapstructure:"user"`
		Password string `mapstructure:"password"`
	} `mapstructure:"rabbit_mq"`
	Cn2En service.TranslationConfig `mapstructure:"cn2en"`
	En2Cn service.TranslationConfig `mapstructure:"en2cn"`
}

// rabbit_mq队列配置
type RabbitMQConfig struct {
	MqURL            string
	Ch2enQueue       string
	En2chQueue       string
	Ch2enResultQueue string
	En2chResultQueue string
	EnCheckQueue     string
	ChCheckQueue     string
}

/*
* 核心业务主程序
* 后台运行 nohup go run main.go 2>&1 &
**/
func main() {
	// 设置工作路径
	setProjectRoot()

	// 调用业务逻辑实现翻译服务

	// 加载配置
	config, err := loadConfig()
	if err != nil {
		// note: 定义为系统级别错误，如果需要添加前缀就使用 字符串 + err.Error()，单独使用err构建那么使用函数 NewSystemErrorFromError
		exception.LogError(exception.NewSystemError("加载配置失败" + err.Error()))
		return
	}

	// 构建 MQ URL
	mqURL := fmt.Sprintf("amqp://%s:%s@%s:%d/",
		config.RabbitMQ.User,
		config.RabbitMQ.Password,
		config.RabbitMQ.Host,
		config.RabbitMQ.Port,
	)

	// 构建rabbit_mq队列配置
	rabbitMQConfig := RabbitMQConfig{
		MqURL:            mqURL,
		Ch2enQueue:       "input_queue",
		En2chQueue:       "cn2en_queue",
		Ch2enResultQueue: "cn2en_queue",
		En2chResultQueue: "en2cn_queue",
		EnCheckQueue:     "en_check_queue",
		ChCheckQueue:     "cn_check_queue",
	}

	// 创建统计信息
	statistics := service.NewStatistics()

	// 创建翻译器实例
	translator := service.NewAPITranslator(config.Cn2En, config.En2Cn)

	// 创建翻译服务实例
	translationService, err := createTranslationService(mqURL, translator, rabbitMQConfig)
	if err != nil {
		exception.LogError(exception.NewSystemError("创建翻译服务失败" + err.Error()))
		return
	}

	// 启动翻译服务
	if err := translationService.Start(statistics); err != nil {
		exception.LogError(exception.NewSystemError("启动翻译服务失败" + err.Error()))
		return
	}

	// 确保资源释放,析构函数
	defer translationService.Close()

	exception.LogInfo("翻译服务已启动")

	// 开启查重服务
	// 创建一个带超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()

	// 连接到 gRPC 服务器
	conn, err := grpc.DialContext(ctx, "grpccheckservice.imagedetect:80", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
	if err != nil {
		exception.LogError(exception.NewSystemError("连接服务器失败" + err.Error()))
		return
	}
	defer conn.Close()

	client := check.NewCheckClient(conn)

	checkServiceConfig := service.NewCheckService()

	service.StartCheckService(mqURL, rabbitMQConfig.ChCheckQueue, rabbitMQConfig.EnCheckQueue, checkServiceConfig, client, statistics)

	select {} // 阻塞主线程
}

// 创建翻译服务器实例
func createTranslationService(mqURL string, translator *service.APITranslator, rabbitMQConfig RabbitMQConfig) (*service.TranslationService, error) {
	translationService, err := service.NewTranslationService(struct {
		MqURL            string
		Ch2enQueue       string
		En2chQueue       string
		Ch2enResultQueue string
		En2chResultQueue string
		EnCheckQueue     string
		ChCheckQueue     string
		Translator       service.Translator
	}{
		MqURL:            mqURL,
		Ch2enQueue:       rabbitMQConfig.Ch2enQueue,
		En2chQueue:       rabbitMQConfig.En2chQueue,
		Ch2enResultQueue: rabbitMQConfig.Ch2enResultQueue,
		En2chResultQueue: rabbitMQConfig.En2chResultQueue,
		EnCheckQueue:     rabbitMQConfig.EnCheckQueue,
		ChCheckQueue:     rabbitMQConfig.ChCheckQueue,
		Translator:       translator,
	})
	if err != nil {
		return nil, err
	}
	return translationService, nil
}

func loadConfig() (*Config, error) {
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath("config")

	if err := viper.ReadInConfig(); err != nil {
		return nil, err
	}

	var config Config
	if err := viper.Unmarshal(&config); err != nil {
		return nil, err
	}

	return &config, nil
}

// 设置工作路径，并完成路径变更
func setProjectRoot() {
	projectRoot := "../.." // 替换为你的项目根目录路径
	if err := os.Chdir(projectRoot); err != nil {
		exception.LogError(exception.NewSystemError("设置工作目录失败" + err.Error()))
	}
}
